﻿using System;
using Autodesk.Revit.DB;
using YJKArch.Utils;
using TopologySearch;

namespace YJKArch.Aproll.DataDefine
{
	public class WallData
	{
		public EdgeInfo PositiveLine
		{
			get
			{
				return this.m_PositiveLine;
			}
			set
			{
				this.m_PositiveLine = value;
			}
		}

		public EdgeInfo NegativeLine
		{
			get
			{
				return this.m_NegativeLine;
			}
			set
			{
				this.m_NegativeLine = value;
			}
		}

		public EdgeInfo CenterLine
		{
			get
			{
				return this.m_CenterLine;
			}
			set
			{
				this.m_CenterLine = value;
			}
		}

		public ElementId Id
		{
			get
			{
				return this.m_Id;
			}
		}

		public bool FindedPositive
		{
			get
			{
				return this.m_FindedPositive;
			}
			set
			{
				if (value)
				{
					this.m_FindedPositive = value;
				}
			}
		}

		public bool FindedNegative
		{
			get
			{
				return this.m_FindedNegative;
			}
			set
			{
				if (value)
				{
					this.m_FindedNegative = value;
				}
			}
		}

		public WallData(WallData rhs)
		{
			this.m_PositiveLine = rhs.m_PositiveLine;
			this.m_NegativeLine = rhs.m_NegativeLine;
			this.m_CenterLine = rhs.m_CenterLine;
			this.m_Id = rhs.m_Id;
		}

		public WallData(EdgeInfo positiveLine, EdgeInfo negativeLine, EdgeInfo centerLine, ElementId id)
		{
			this.m_PositiveLine = positiveLine;
			this.m_NegativeLine = negativeLine;
			this.m_CenterLine = centerLine;
			this.m_Id = id;
		}

		public WallData(EdgeInfo centerLine, ElementId id, double positiveThickness, double negativeThickness)
		{
			this.m_CenterLine = centerLine;
			this.m_Id = id;
			this.OffsetDoubleLine(centerLine, positiveThickness, negativeThickness);
		}

		public Pole2D ConvertToPole2D()
		{
			bool positiveDirection = true;
			return new Pole2D(this.m_Id, this.m_CenterLine.StartPoint, this.m_CenterLine.EndPoint, this.m_CenterLine.Bulge, this.m_PositiveLine.StartPoint, this.m_PositiveLine.EndPoint, this.m_NegativeLine.StartPoint, this.m_NegativeLine.EndPoint, positiveDirection);
		}

		public bool IsOutWall(ref WallData.OutWallOrientations orientations)
		{
			if (this.m_FindedNegative && this.m_FindedPositive)
			{
				orientations = WallData.OutWallOrientations.OWO_Two_Sided;
				return false;
			}
			if (this.m_FindedPositive)
			{
				orientations = WallData.OutWallOrientations.OWO_Positive;
				return true;
			}
			if (this.m_FindedNegative)
			{
				orientations = WallData.OutWallOrientations.OWO_Negative;
				return true;
			}
			orientations = WallData.OutWallOrientations.OWO_None;
			return false;
		}

		public bool Linked(WallData wallData)
		{
			return Geometry.IsEqual(this.CenterLine.StartPoint, wallData.CenterLine.StartPoint, 0.0001) || Geometry.IsEqual(this.CenterLine.StartPoint, wallData.CenterLine.EndPoint, 0.0001) || Geometry.IsEqual(this.CenterLine.EndPoint, wallData.CenterLine.StartPoint, 0.0001) || Geometry.IsEqual(this.CenterLine.EndPoint, wallData.CenterLine.EndPoint, 0.0001);
		}

		public bool GetOrientation(ref XYZ orientation)
		{
			WallData.OutWallOrientations outWallOrientations = WallData.OutWallOrientations.OWO_None;
			if (!this.IsOutWall(ref outWallOrientations))
			{
				return false;
			}
			if (this.m_PositiveLine.IsArc)
			{
				XYZ xyz = XYZ.BasisZ;
				if (Geometry.LessThan(this.m_PositiveLine.Bulge, 0.0))
				{
					xyz = -xyz;
				}
				XYZ ptCenter = null;
				Geometry.GetCenterWithBulge(this.m_PositiveLine.StartPoint, this.m_PositiveLine.EndPoint, this.m_PositiveLine.Bulge, ref ptCenter);
				XYZ xyz2 = Geometry.CalculatMidPoint(this.m_PositiveLine.StartPoint, this.m_PositiveLine.EndPoint, ptCenter, xyz);
				XYZ xyz3 = Geometry.CalculatMidPoint(this.m_NegativeLine.StartPoint, this.m_NegativeLine.EndPoint, ptCenter, xyz);
				if (this.m_FindedPositive)
				{
					orientation = (xyz3 - xyz2).Normalize();
				}
				else if (this.m_FindedNegative)
				{
					orientation = (xyz2 - xyz3).Normalize();
				}
			}
			else if (this.m_FindedPositive)
			{
				orientation = (this.m_NegativeLine.StartPoint - this.m_PositiveLine.StartPoint).Normalize();
			}
			else if (this.m_FindedNegative)
			{
				orientation = (this.m_PositiveLine.StartPoint - this.m_NegativeLine.StartPoint).Normalize();
			}
			return true;
		}

		public bool GetRealOutSideLine(Autodesk.Revit.DB.Document doc, ref EdgeInfo edgeInfo)
		{
			Wall wall = doc.GetElement(this.Id) as Wall;
			if (wall == null)
			{
				return false;
			}
			XYZ orientation = wall.Orientation;
			XYZ ptOut = null;
			if (!this.GetOrientation(ref ptOut))
			{
				return false;
			}
			double angle = Geometry.getAngle(XYZ.Zero, ptOut);
			double angle2 = Geometry.getAngle(XYZ.Zero, orientation);
			double val = Geometry.IntersectionAngle(angle, angle2);
			if (Geometry.GreaterThan(val, Math.PI*.5))
			{
				edgeInfo = this.NegativeLine;
			}
			else
			{
				edgeInfo = this.PositiveLine;
			}
			XYZ pt = (edgeInfo.EndPoint - edgeInfo.StartPoint).Normalize();
			if (Geometry.LessThan(edgeInfo.Bulge, 0.0))
			{
				pt = (edgeInfo.StartPoint - edgeInfo.EndPoint).Normalize();
			}
			XYZ ptOut2 = Geometry.RotateTo(pt, -Math.PI*.5, XYZ.BasisZ);
			Geometry.IntersectionAngle(Geometry.getAngle(XYZ.Zero, ptOut2), angle2);
			if (Geometry.GreaterThan(val, Math.PI*.5))
			{
				edgeInfo.ReverseSelf();
			}
			return true;
		}

		protected void OffsetDoubleLine(EdgeInfo centerLine, double positiveThickness, double negativeThickness)
		{
			if (centerLine.IsArc)
			{
				bool flag = true;
				if (Geometry.IsEqual(centerLine.Normal, -XYZ.BasisZ, 0.0001))
				{
					flag = false;
				}
				double num = -1.0;
				if (flag)
				{
					num = 1.0;
				}
				this.m_NegativeLine = EdgeInfo.Offset(centerLine, -negativeThickness * num);
				this.m_PositiveLine = EdgeInfo.Offset(centerLine, positiveThickness * num);
				return;
			}
			this.m_NegativeLine = EdgeInfo.Offset(centerLine, -negativeThickness);
			this.m_PositiveLine = EdgeInfo.Offset(centerLine, positiveThickness);
		}

		private EdgeInfo m_PositiveLine;

		private EdgeInfo m_NegativeLine;

		private EdgeInfo m_CenterLine;

		private ElementId m_Id;

		private bool m_FindedPositive;

		private bool m_FindedNegative;

		public enum OutWallOrientations : uint
		{
			OWO_None,
			OWO_Positive,
			OWO_Negative,
			OWO_Two_Sided
		}
	}
}
